#******************************************************************************
#******************************************************************************

# import libraries

# import numpy as np

from dataclasses import dataclass, InitVar #, field

from .classes import StandardisedPipeDatabase, InsulatedPipe
    
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

@dataclass
class InsulatedTwinPipe(InsulatedPipe):
    """A class for insulated cylindrical twin pipes."""
    pipe_center_distance: float = None
    
    def ValidateInsulatedTwinPipe(self):
        
        # the distance must be positive
        
        assert self.pipe_center_distance > 0
        
        # the distance must be greater than self.d_ext
        
        assert self.pipe_center_distance >= self.d_ext
        
        # the distance must not exceed self.d_cas - self.d_ext
        
        assert self.pipe_center_distance <= self.d_cas-self.d_ext
    
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************

# note: all twin pipes are generally insulated pipes

@dataclass
class StandardisedTwinPipe(InsulatedTwinPipe):
    """A class for standardised cylindrical twin pipes."""
    pipe_tuple: tuple = None            # (DN,S)
    e_rel: float = None                 # relative roughness
    sp: float = None                    # specific price
    p_rated: float = None               # rated pressure
    db: InitVar[StandardisedPipeDatabase] = None
    
    def __post_init__(self, db):
        
        # class instances can be created using a database or manually
        
        if db != None:
            
            # a database has been specified
            
            # check if the database has information about the pipe
        
            if self.pipe_tuple in db.pipe_tuples:
                
                # get data from the database
                
                self.d_int = db.d_int[self.pipe_tuple]
                
                self.d_ext = db.d_ext[self.pipe_tuple]
                
                self.d_ins = db.d_ins[self.pipe_tuple]
                
                self.d_cas = db.d_cas[self.pipe_tuple]
                
                self.k = db.k_pipe[self.pipe_tuple]
                
                self.k_ins = db.k_ins[self.pipe_tuple]
                
                self.k_cas = db.k_cas[self.pipe_tuple]
            
                self.p_rated = db.p_rated[self.pipe_tuple]
                
                #self.make_ref = db.make_ref_tuples[self.pipe_tuple]
                
                self.pipe_center_distance = (
                    db.pipe_dist[self.pipe_tuple]+self.d_ext
                    )
                
                # if sp has not been defined manually...
                
                if self.sp == None:
                    
                    # ...get it from the data base
                
                    self.sp = db.sp[self.pipe_tuple]
                    
                # if length has not been defined manually...
                
                if self.length == None:
                    
                    # ...get it from the data base
                
                    self.length = db.length[self.pipe_tuple]
                    
                # there are 3 ways to define the pipe roughness:
                # 1) by defining directly
                # 2) by defining indirectly via the relative pipe roughness
                # 3) via a database (neither one or the other)
        
                # if e_rel has not been defined manually...
                
                if (self.e_rel == None and self.e_eff == None):
                    
                    # ... get e_eff from the database and...
                
                    self.e_eff = db.e_eff[self.pipe_tuple]
                
                    # ... compute e_rel with it
                    
                    self.e_rel = self.e_eff/self.d_int
                    
                elif (self.e_rel == None and self.e_eff != None):
                    
                    # direct method
                    
                    self.e_rel = self.e_eff/self.d_int
                
                else: 
                    
                    # indirect method
                    
                    self.e_eff = self.d_int*self.e_rel
                    
                #**************************************************************
                
            else:
                
                # print
                
                print('StandardisedPipe: something is up with the post-init phase.')
                
                raise SystemExit
                
        else:
            
            # no database has been specified, i.e., manual mode
            
            if self.e_rel != None and self.e_eff == None:
                
                # the absolute roughness has not been specified
                
                self.e_eff = self.e_rel*self.d_int
                
            elif self.e_rel == None and self.e_eff != None:
                
                # the relative roughness has not been specified
                
                self.e_rel = self.e_eff/self.d_int
            
        #**********************************************************************
        #**********************************************************************
    
    #**************************************************************************
    #**************************************************************************
    
    def ValidateStandardisedTwinPipe(self):
        
        # validate inherited attributes
        
        self.ValidateInsulatedTwinPipe()
    
        # the relative roughness must be non-negative
        
        assert self.e_rel >= 0
        
        # the price must be non-negative
        
        assert self.sp >= 0
        
        # the rated pressure must be positive
        
        assert self.p_rated > 0
        
        # the input tuple must be in the database or be None
        
        assert (
            (self.pipe_tuple in self.db.pipe_tuples 
             if self.db != None else True) or
            (self.pipe_tuple == None)
            )
    
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************
#******************************************************************************